home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / displytl / xvsunras.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  10.5 KB  |  447 lines

  1. /*
  2.  * xvsunras.c - load routine for 'sun rasterfile' format pictures
  3.  *
  4.  * LoadSunRas(fname, numcols)  -  loads a PM pic, does 24to8 code if nec.
  5.  * WriteSunRas(fp, pic, w, h, r,g,b, numcols, style)
  6.  * WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
  7.  *
  8.  * This file written by Dave Heath (heath@cs.jhu.edu)
  9.  * fixBGR() added by Ken Rossman (ken@shibuya.cc.columbia.edu)
  10.  */
  11.  
  12.  
  13. #include "xvimage.h"
  14. #include "xvsunras.h"
  15.  
  16. static int  SunRasError();
  17. static int  rle_read();
  18. static void flipl();
  19. static void SunRas1to8();
  20. static void SunRas8to1();
  21. static int  write_sun_long();
  22. static void fixBGR();
  23.  
  24.  
  25. /*******************************************/
  26. int LoadSunRas(fname,nc)
  27.      char *fname;
  28.      int   nc;
  29. /*******************************************/
  30. {
  31.   FILE    *fp;
  32.   int     linesize,lsize,csize,isize,flipit,i,w,h,d,rv;
  33.   byte     *image, *line;
  34.   struct rasterfile sunheader;
  35.  
  36.   rv = 0;
  37.  
  38.   /* read in the Sun Rasterfile picture */
  39.   fp=fopen(fname,"r");
  40.   if (!fp) return( SunRasError("unable to open file") );
  41.  
  42.   flipit = 0;
  43.   fread(&sunheader,sizeof(struct rasterfile),1,fp);
  44.   if (sunheader.ras_magic != RAS_MAGIC)
  45.   {
  46.     flipl( (byte *) &sunheader.ras_magic);
  47.     if (sunheader.ras_magic == RAS_MAGIC) flipit = 1;
  48.     else flipl( (byte *) &sunheader.ras_magic);
  49.   }
  50.   if (sunheader.ras_magic != RAS_MAGIC) 
  51.     return( SunRasError("not a Sun rasterfile") );
  52.  
  53.   if (flipit) {
  54.     flipl((byte *) &sunheader.ras_width);
  55.     flipl((byte *) &sunheader.ras_height);
  56.     flipl((byte *) &sunheader.ras_depth);
  57.     flipl((byte *) &sunheader.ras_length);
  58.     flipl((byte *) &sunheader.ras_type);
  59.     flipl((byte *) &sunheader.ras_maptype);
  60.     flipl((byte *) &sunheader.ras_maplength);
  61.     }
  62.  
  63.   /* make sure that the input picture can be dealt with */
  64.   if (sunheader.ras_depth != 1 &&
  65.       sunheader.ras_depth != 8 &&
  66.       sunheader.ras_depth != 24 &&
  67.       sunheader.ras_depth != 32) {
  68.     fprintf (stderr, "Sun rasterfile image has depth %d\n", 
  69.          sunheader.ras_depth);
  70.     fprintf (stderr, "Depths supported are 1, 8, 24, and 32\n");
  71.     return 1;
  72.   }
  73.  
  74.   if (sunheader.ras_type != RT_OLD &&
  75.       sunheader.ras_type != RT_STANDARD &&
  76.       sunheader.ras_type != RT_BYTE_ENCODED &&
  77.       sunheader.ras_type != RT_FORMAT_RGB) {
  78.     fprintf(stderr, "Sun rasterfile of unsupported type %d\n",
  79.          sunheader.ras_type);
  80.     return 1;
  81.   }
  82.  
  83.   if (sunheader.ras_maptype != RMT_RAW &&
  84.       sunheader.ras_maptype != RMT_NONE &&
  85.       sunheader.ras_maptype != RMT_EQUAL_RGB) {
  86.     fprintf(stderr, "Sun rasterfile colormap of unsupported type %d\n",
  87.          sunheader.ras_maptype);
  88.     return 1;
  89.   }
  90.  
  91.   w = sunheader.ras_width;
  92.   h = sunheader.ras_height;
  93.   d = sunheader.ras_depth;
  94.   isize = sunheader.ras_length ?
  95.       sunheader.ras_length :
  96.       (w * h * d) / 8;
  97.   csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength;
  98.  
  99.   /* compute length of the output (xv-format) image */
  100.   lsize = w * h;     
  101.   if (d == 24 || d == 32) lsize = lsize * 3;
  102.  
  103.   linesize = w * d;
  104.   /* if ((linesize % 48) && d == 24) linesize += (48 - (linesize % 48)); */
  105.   if (linesize % 16) linesize += (16 - (linesize % 16));
  106.   linesize /= 8;
  107.  
  108.   if (DEBUG)
  109.   {
  110.     fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n",
  111.         cmd, w, h,
  112.         d);
  113.     fprintf (stderr, 
  114.        "type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n",
  115.          sunheader.ras_type, sunheader.ras_maptype,
  116.          isize, csize, lsize, linesize);
  117.   }
  118.  
  119.   sprintf(formatStr, "Sun %s rasterfile.  (%d plane%s)  (%d bytes)",
  120.       sunheader.ras_type == RT_BYTE_ENCODED ? "rle" : "standard",
  121.       d,
  122.       d == 1 ? "" : "s",
  123.       sizeof (struct rasterfile) + csize + isize);
  124.  
  125.   /* read in the colormap, if any */
  126.   if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize)
  127.   {
  128.     fread (r, sizeof (byte), sunheader.ras_maplength/3, fp);
  129.     fread (g, sizeof (byte), sunheader.ras_maplength/3, fp);
  130.     fread (b, sizeof (byte), sunheader.ras_maplength/3, fp);
  131.  
  132.    /* for (i = 0; i < sunheader.ras_maplength/3; i++)
  133.     {
  134.       r[i] = getc (fp);
  135.       g[i] = getc (fp);
  136.       b[i] = getc (fp);
  137.     } */
  138.   }
  139.   else if (sunheader.ras_maptype == RMT_RAW && csize)
  140.   {
  141.     /* we don't know how to handle raw colormap, ignore */
  142.     fseek (fp, (long) csize, 1);
  143.   }
  144.  
  145.   else {  /* no colormap, make one up */
  146.     if (sunheader.ras_depth == 1) {
  147.       r[0] = g[0] = b[0] = 0;
  148.       r[1] = g[1] = b[1] = 255;
  149.     }
  150.  
  151.     else if (sunheader.ras_depth == 8) {
  152.       for (i = 0; i < 256; i++)
  153.     r[i] = g[i]  = b[i] = i;
  154.     }
  155.   }
  156.  
  157.  
  158.   /* allocate memory for picture and read it in */
  159.   /* note we may slightly overallocate here (if image is padded) */
  160.   image = (byte *) malloc (lsize);
  161.   line = (byte *) malloc (linesize);
  162.   if (image == NULL || line == NULL)
  163.     FatalError("Can't allocate memory for image\n");
  164.  
  165.   for (i = 0; i < h; i++) {
  166.     if (sunheader.ras_type == RT_BYTE_ENCODED) {
  167.       if (rle_read (line, 1, linesize, fp, (i==0)) != linesize) break;
  168.     /* return (SunRasError ("rle file read error")); */
  169.     }
  170.  
  171.     else {
  172.       if (fread (line, 1, linesize, fp) != linesize)
  173.     return (SunRasError ("file read error"));
  174.     }
  175.  
  176.     switch (d) {
  177.     case 1:  SunRas1to8 (image + w * i, line, w);    break;
  178.     case 8:  memcpy (image + w * i, line, w);        break;
  179.     case 24: memcpy (image + w * i * 3, line, w * 3); break;
  180.     case 32: {
  181.                int k;
  182.                byte *ip, *op;
  183.            ip = line;
  184.            op = (byte *) (image + w * i * 3);
  185.            for (k = 0; k<w; k++) {
  186.          *ip++;           /* skip 'alpha' */
  187.          *op++ = *ip++;   /* red   */
  188.          *op++ = *ip++;   /* green */
  189.          *op++ = *ip++;   /* blue  */
  190.            }
  191.          }
  192.     }
  193.   }
  194.  
  195.   if (fp != stdin) fclose (fp);
  196.   if (DEBUG) fprintf(stderr,"Sun ras: image loaded!\n");
  197.  
  198.   if (d == 24 || d == 32) {
  199.     if (sunheader.ras_type != RT_FORMAT_RGB) fixBGR(image,w,h);
  200.     rv = Conv24to8 (image, w, h, nc);
  201.     free (image);
  202.     return (rv);
  203.   }
  204.  
  205.   else {
  206.     pic = image;
  207.     pWIDE = w;
  208.     pHIGH = h;
  209.     return (0);
  210.   }
  211. }
  212.  
  213.  
  214. /*****************************/
  215. static int rle_read (ptr, size, nitems, fp, init)
  216. byte *ptr;
  217. int size, nitems,init;
  218. FILE *fp;
  219. {
  220.   static int count, ch;
  221.   int readbytes, c, read;
  222.  
  223.   if (init) { count = ch = 0; }
  224.  
  225.   readbytes = size * nitems;
  226.   for (read = 0; read < readbytes; read++) {
  227.     if (count) {
  228.       *ptr++ = (byte) ch;
  229.       count--;
  230.     }
  231.  
  232.     else {
  233.       c = getc(fp);
  234.       if (c == EOF) break;
  235.  
  236.       if (c == RAS_RLE) {   /* 0x80 */
  237.     count = getc(fp);
  238.     if (count == EOF) break;
  239.  
  240.     if (count < 0) count &= 0xff;
  241.     if (count == 0) *ptr++ = c;
  242.         else {
  243.           if ((ch = getc(fp)) == EOF) break;
  244.           *ptr++ = ch;
  245.         }
  246.       }
  247.       else *ptr++ = c;
  248.     }
  249.   }
  250.  
  251.   return (read/size);
  252. }
  253.  
  254.  
  255. /*****************************/
  256. static int SunRasError(st)
  257. char *st;
  258. {
  259.   printf("LoadSunRas() - %s\n",st);
  260.   return -1;
  261. }
  262.  
  263.  
  264. /*****************************/
  265. static void flipl(p)
  266.      byte *p;
  267. {
  268.   byte t;
  269.   t = p[0];  p[0]=p[3];  p[3] = t;
  270.   t = p[1];  p[1]=p[2];  p[2] = t;
  271. }
  272.  
  273.  
  274. static void SunRas1to8 (dest, src, len)
  275. byte *dest, *src;
  276. int len;
  277. {
  278.   int i, b;
  279.   int c;
  280.  
  281.   for (i = 0, b = -1; i < len; i++) {
  282.     if (b < 0) {
  283.       b = 7;
  284.       c = ~*src++;
  285.     }
  286.     *dest++ = ((c >> (b--)) & 1);
  287.   }
  288. }
  289.  
  290.  
  291.  
  292. static void SunRas8to1 (dest, src, len)
  293. byte *dest, *src;
  294. int len;
  295. {
  296.   int i, b;
  297.   int c;
  298.  
  299.   for (c = b = i = 0; i < len; i++) {
  300.     c <<= 1;
  301.     c |= (*src++ ? 0 : 1);
  302.     if (b++ == 7) {
  303.       *dest++ = c;
  304.       b = c = 0;
  305.     }
  306.   }
  307.   if (b) *dest = c;
  308. }
  309.  
  310.  
  311.  
  312.  
  313. /*******************************************/
  314. int WriteSunRas(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,userle)
  315. FILE *fp;
  316. byte *pic;
  317. int   w,h;
  318. byte *rmap, *gmap, *bmap;
  319. int   numcols, colorstyle, userle;
  320. {
  321.   /* writes a sun rasterfile to the already open stream
  322.      writes either 8-bit or 1-bit (never 24)
  323.      currently will not write rle files
  324.  
  325.      biggest problem w/ rle file: should we compute
  326.      image size first (nicer) or go back and write it
  327.      in when we are done (kludgy)?
  328.    */
  329.  
  330.   struct rasterfile sunheader;
  331.   int linesize, i, color, d, y;
  332.   byte *line;
  333.  
  334.   if (colorstyle != 2 && numcols > 2) d = 8;
  335.   else d = 1;
  336.  
  337.   linesize = w;
  338.   if (d == 1) {
  339.     if (linesize % 8) linesize += (8 - linesize % 8);
  340.     linesize /= 8;
  341.   }
  342.  
  343.   if (linesize % 2) linesize++;
  344.   line = (byte *) malloc (linesize);
  345.   if (!line) {
  346.     printf("Can't allocate memory for save!\n");
  347.     return (1);
  348.   }
  349.  
  350.   if (DEBUG)
  351.     fprintf (stderr,
  352.          "WriteSunRas: d %d, linesize %d numcols %d\n",
  353.          d, linesize, numcols);
  354.  
  355.   /* set up the header */
  356.   sunheader.ras_magic      = RAS_MAGIC;
  357.   sunheader.ras_width      = w;
  358.   sunheader.ras_height      = h;
  359.   sunheader.ras_depth      = d;
  360.   sunheader.ras_length      = linesize * h;
  361.   sunheader.ras_type      = RT_STANDARD;
  362.   sunheader.ras_maptype   = (d == 1) ? RMT_NONE : RMT_EQUAL_RGB;
  363.   sunheader.ras_maplength = (d == 1) ? 0 : 3 * numcols;
  364.  
  365.   write_sun_long (sunheader.ras_magic     , fp);
  366.   write_sun_long (sunheader.ras_width     , fp);
  367.   write_sun_long (sunheader.ras_height     , fp);
  368.   write_sun_long (sunheader.ras_depth     , fp);
  369.   write_sun_long (sunheader.ras_length     , fp);
  370.   write_sun_long (sunheader.ras_type     , fp);
  371.   write_sun_long (sunheader.ras_maptype  , fp);
  372.   write_sun_long (sunheader.ras_maplength, fp);
  373.  
  374.   /* write the colormap */
  375.   if (d > 1)
  376.     if (colorstyle == 1)  /* grayscale */
  377.       for (color = 0; color < 3; color++)
  378.     for (i = 0; i < numcols; i++)
  379.       putc (MONO(rmap[i],gmap[i],bmap[i]), fp);
  380.     else {
  381.       fwrite (rmap, sizeof (byte), numcols, fp);
  382.       fwrite (gmap, sizeof (byte), numcols, fp);
  383.       fwrite (bmap, sizeof (byte), numcols, fp);
  384.     }
  385.  
  386.   /* write the image */
  387.   line[linesize-1] = 0;
  388.   for (y = 0; y < h; y++) {
  389.  
  390.     if (d > 1)
  391.       memcpy (line, pic + y * w, w);
  392.     else
  393.       SunRas8to1 (line, pic + y * w, w);
  394.  
  395.     if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
  396.       printf("Write failed during save!\n");
  397.       free (line);
  398.       return (2);
  399.     }
  400.   }
  401.  
  402.   free (line);
  403.   return (0);
  404. }
  405.  
  406.  
  407. /* write a long word in sun byte-order
  408.    returns 0 for success, EOF for failure
  409.  */
  410. static int write_sun_long (l, fp)
  411. long l;
  412. FILE *fp;
  413. {
  414.     char c;
  415.  
  416.     c = ((l >> 24) & 0xff);
  417.     if (putc (c, fp) == EOF) return (EOF);
  418.     c = ((l >> 16) & 0xff);
  419.     if (putc (c, fp) == EOF) return (EOF);
  420.     c = ((l >> 8) & 0xff);
  421.     if (putc (c, fp) == EOF) return (EOF);
  422.     c = (l & 0xff);
  423.     if (putc (c, fp) == EOF) return (EOF);
  424.     return (0);
  425. }
  426.  
  427.  
  428.  
  429.  
  430. /* kr3 - fix up BGR order SUN 24-bit rasters to be RGB order */
  431. static void fixBGR(img,w,h)
  432. unsigned char *img;
  433. int w,h;
  434. {
  435.   int i,npixels;
  436.   unsigned char tmp;
  437.  
  438.   npixels = w*h;
  439.   for (i=0; i<npixels; i++) {
  440.     tmp = img[0];                   /* swap red and blue channels */
  441.     img[0] = img[2];
  442.     img[2] = tmp;
  443.     img += 3;                       /* bump to next pixel */
  444.   }
  445. }
  446.  
  447.